package cn.micro.system.manage.common.utils;

import cn.micro.system.manage.common.component.RedisService;
import cn.micro.system.manage.common.constants.SecurityConstants;
import cn.micro.system.manage.common.exception.SystemException;
import cn.micro.system.manage.common.result.ResultCodeEnum;
import cn.micro.system.manage.common.utils.uuid.IdUtils;
import cn.micro.system.manage.entity.vo.LoginUserDetailVO;
import io.jsonwebtoken.*;
import org.springframework.beans.factory.annotation.Value;

import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;

import java.util.Date;

/**
 * 生成JSON Web令牌的工具类
 */
@Component
public class JwtHelper {

    //token过期时间
    @Value("${auth.token.expire}")
    private long tokenExpiration;
    //加密秘钥
    @Value("${auth.token.secret_key}")
    private String tokenSignKey;

    @Resource
    private RedisService redisService;

    /**
     * secret key byte array.
     */
    private byte[] secretKeyBytes;

    //根据用户id和用户名称生成token字符串
    public String createToken(String userId, String username) {
        String token = Jwts.builder()
                .setSubject("AUTH-USER")
                .setExpiration(new Date(System.currentTimeMillis() + tokenExpiration))
                .claim("jti", IdUtils.fastSimpleUUID())
                .claim("userId", userId)
                .claim("username", username)
                .signWith(SignatureAlgorithm.HS512, tokenSignKey)
                .compressWith(CompressionCodecs.GZIP)
                .compact();
        return token;
    }

    //从token字符串获取userid
    public String getUserId(String token) {
        try {
            if (StringUtils.isEmpty(token)) return null;
            Jws<Claims> claimsJws = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token);
            Claims claims = claimsJws.getBody();
            String userId = (String) claims.get("userId");
            return userId;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    //从token字符串获取username
    public String getUsername(String token) {
        try {
            if (StringUtils.isEmpty(token)) return "";

            Jws<Claims> claimsJws = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token);
            Claims claims = claimsJws.getBody();
            return (String) claims.get("username");
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }


    /**
     * 获取认证信息
     */
    public Authentication getAuthentication(Claims claims) {
        LoginUserDetailVO principal = new LoginUserDetailVO();
        principal.setUserId(Long.parseLong(claims.get("userId").toString())); // 用户ID
        principal.setUsername(claims.get("username").toString()); // 用户名
        return new UsernamePasswordAuthenticationToken(principal, "", null);
    }

    /**
     * 通过json返回用户信息
     * @param token
     * @return
     */
    public LoginUserDetailVO getLoginUserDetail(String token){
        try {
            if (StringUtils.isEmpty(token)) return null;
            Jws<Claims> claimsJws = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token);
            Claims claims = claimsJws.getBody();
            LoginUserDetailVO principal = new LoginUserDetailVO();
            principal.setUserId(Long.parseLong(claims.get("userId").toString())); // 用户ID
            principal.setUsername(claims.get("username").toString()); // 用户名
            return principal;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 通过json返回用户信息
     * @return
     */
    public LoginUserDetailVO getLoginUserDetail(Claims claims){
        try {
            LoginUserDetailVO principal = new LoginUserDetailVO();
            principal.setUserId(Long.parseLong(claims.get("userId").toString())); // 用户ID
            principal.setUsername(claims.get("username").toString()); // 用户名
            return principal;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }


    /**
     * 解析 & 验证 token
     */
    public Claims parseAndValidateToken(String token) {
        // 解析成功说明JWT有效
        Claims claims = this.getTokenClaims(token);
        // 验证JWT 是否在黑名单(注销场景会存入黑名单)
        Boolean isBlack = redisService.hasKey(SecurityConstants.BLACK_TOKEN_CACHE_PREFIX + claims.get("jti").toString());
        if (isBlack) {
            throw new SystemException(ResultCodeEnum.FAIL.getCode(),"token 已被禁用");
        }
        return claims;
    }

    /**
     * get token claims
     */
    public Claims getTokenClaims(String token) {
        if (StringUtils.isEmpty(token)) return null;
        Jws<Claims> claimsJws = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token);
        Claims claims = claimsJws.getBody();
        return claims;
    }





    public static void main(String[] args) {
//        String token = JwtHelper.createToken("1", "test");
//        System.out.println(token);
//
//        String userId = JwtHelper.getUserId(token);
//        System.out.println(userId);
//
//        String username = JwtHelper.getUsername(token);
//        System.out.println(username);
    }
}